package com.egzosn.controller.pay;

import com.egzosn.entity.pay.PayType;
import com.egzosn.pay.common.api.PayConfigStorage;
import com.egzosn.pay.common.api.PayService;
import com.egzosn.pay.common.bean.*;
import com.egzosn.pay.common.util.str.StringUtils;
import com.egzosn.request.QueryOrder;
import com.egzosn.service.pay.PayApplyService;
import com.egzosn.service.pay.PayResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;


/**
 * 支付
 * @author  egan
 * @email egzosn@gmail.com
 * @date 2016-5-31
 */
@RestController
@RequestMapping("pay")
public class PayController{

    @Autowired
    private PayApplyService service;



    /**
     * 获取支付预订单信息
     *
     * @param payId           支付账户id
     * @param applyId         账单订单id
     * @return 支付预订单信息
     */
    @RequestMapping("app")
    public Map<String, Object> app(Integer payId, String applyId, BigDecimal price) {

        if (StringUtils.isEmpty(applyId)){
            applyId = UUID.randomUUID().toString().replace("-", "");
        }
        //获取对应的支付账户操作工具（可根据账户id）
        PayResponse payResponse = service.getPayResponse(payId);
        Map<String, Object> data = new HashMap<>();
        data.put("code", 0);
        PayOrder order = new PayOrder("订单title", "摘要", null == price ? new BigDecimal(0.01) : price, applyId, PayType.valueOf(payResponse.getStorage().getPayType()).getTransactionType("app"));
        data.put("data", payResponse.getService().orderInfo(order));
        return data;
    }



    /**
     * 跳到支付页面
     * 针对实时支付,即时付款
     *
     * @param payId           账户id
     * @param applyId         账单订单id
     * @param transactionType 交易类型， 这个针对于每一个 支付类型的对应的几种交易方式
     * @param subject        描述
     * @return 跳到支付页面
     */
    @RequestMapping(value = "toPay.html", produces = "text/html;charset=UTF-8")
    public String toPay(Integer payId, String applyId, String subject, String transactionType) {

        if (StringUtils.isEmpty(applyId)){
            return "404";
        }


        //获取对应的支付账户操作工具（可根据账户id）
        PayResponse payResponse = service.getPayResponse(payId);

        if (StringUtils.isEmpty(subject)){
            subject = "订单收款";
        }
        PayOrder payOrder = new PayOrder(subject, subject, new BigDecimal(0.01), applyId, PayType.valueOf(payResponse.getStorage().getPayType()).getTransactionType(transactionType));


        PayService service = payResponse.getService();
        Map orderInfo = service.orderInfo(payOrder);

        String buildRequest = service.buildRequest(orderInfo, MethodType.POST);
        return buildRequest;
    }



    /**
     * 获取二维码图像
     * 二维码支付
     * @param payId 账户id
     * @param transactionType 交易类型
     * @param applyId  账单订单id
     * @return 二维码图像
     * @throws IOException
     */
    @RequestMapping(value = "toQrPay.jpg", produces = "image/jpeg;charset=UTF-8")
    public byte[] toQrPay(Integer payId, String transactionType, String applyId) throws IOException {

        if (StringUtils.isEmpty(applyId)){
            return "404".getBytes();
        }

        //获取对应的支付账户操作工具（可根据账户id）
        PayResponse payResponse = service.getPayResponse(payId);
        try(ByteArrayOutputStream baos = new ByteArrayOutputStream()){
            PayType payType = PayType.valueOf(payResponse.getStorage().getPayType());
            PayOrder payOrder = new PayOrder("订单收款", "订单收款", new BigDecimal(0.01), applyId, payType.getTransactionType(transactionType));
            ImageIO.write(payResponse.getService().genQrPay(payOrder), "JPEG", baos);

            byte[] bytes = baos.toByteArray();
            return bytes;
        }
    }





    /**
     * 支付回调地址
     *
     * @param request
     * @return 支付是否成功
     */
    @RequestMapping(value = "payBack{payId}.json")
    public String payBack(HttpServletRequest request, @PathVariable Integer payId) throws IOException {
        //根据账户id，获取对应的支付账户操作工具
        PayResponse payResponse = service.getPayResponse(payId);
        PayConfigStorage storage = payResponse.getStorage();


        PayService service = payResponse.getService();
        //获取支付方返回的对应参数
        Map<String, Object> params = service.getParameter2Map(request.getParameterMap(), request.getInputStream());
        if (null == params) {

            return service.getPayOutMessage("fail", "失败").toMessage();
        }



        //校验
        if (service.verify(params)) {
            PayMessage message = new PayMessage(params, storage.getPayType(), storage.getMsgType().name());
            PayOutMessage outMessage = payResponse.getRouter().route(message);
            String msg = outMessage.toMessage();
            return msg;
        }



        return service.getPayOutMessage("fail", "失败").toMessage();
    }

    /**
     * 同步回调地址
     *
     * @param request
     * @return 支付是否成功
     */
    @RequestMapping(value = "payBack{payId}.html")
    public String payBackPage(HttpServletRequest request, @PathVariable Integer payId) throws IOException {

        payBack(request, payId);
        return   "<script type=\"text/javascript\"> window.close();</script>";
    }



    /**
     * 查询
     *
     * @param order 订单的请求体
     * @return 返回查询回来的结果集，支付方原值返回
     */
    @RequestMapping("query")
    public Map<String, Object> query(QueryOrder order) {
        PayService service = this.service.getPayResponse(order.getPayId()).getService();
        //支付订单结果集
        return service.query(order.getTradeNo(), order.getOutTradeNo());
    }

    /**
     * 申请退款接口
     *
     * @param order 订单的请求体
     * @return 返回支付方申请退款后的结果
     */
    @RequestMapping("refund")
    public Map<String, Object> refund(Integer payId ,RefundOrder order) {
        PayService service = this.service.getPayResponse(payId).getService();

//        return service.refund(order.getTradeNo(), order.getOutTradeNo(), order.getRefundAmount(), order.getTotalAmount());
        //退款结果集
        Map<String, Object> res = service.refund(order);
        return res;
    }



    /**
     * 下载对账单
     *
     * @param order 订单的请求体
     * @return 返回支付方下载对账单的结果
     */
    @RequestMapping("downloadbill")
    public Object downloadbill(QueryOrder order) {
        PayService service = this.service.getPayResponse(order.getPayId()).getService();
        //对账单结果集
        Map<String, Object> downloadbill = service.downloadbill(order.getBillDate(), order.getBillType());
        return downloadbill;
    }

    /**
     * 转账
     *
     * @param order 转账订单
     *
     * @return 对应的转账结果
     */
    @RequestMapping("transfer")
    public Map<String, Object> transfer(int payId, TransferOrder order) {
        PayService service = this.service.getPayResponse(payId).getService();
        //转账结果
        Map<String, Object> res = service.transfer(order);
        return res;
    }


    /**
     * 转账查询
     *
     * @param outNo   商户转账订单号
     * @param tradeNo 支付平台转账订单号
     *
     * @return 对应的转账订单
     */
    @RequestMapping("transferQuery")
    public Map<String, Object> transferQuery(int payId, String outNo, String tradeNo) {
        PayService service = this.service.getPayResponse(payId).getService();
        //转账查询结果
        Map<String, Object> res = service.transferQuery(outNo, tradeNo);
        return res;
    }

}
